/*
 * Copyright 2014 Matyas Mazzag
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.security.SecureRandom

import org.mcubed.soapui.ConfigFilePathResolver
import org.mcubed.soapui.ScriptFilePathResolver
import org.mcubed.soapui.ScriptRunner

import com.eviware.soapui.support.GroovyUtils


/**
 * Main entry point to calling external groovy code from SoapUI.
 * <br/>
 * Usage: EGL.i { "your.groovy.Script"(parameter1: value, ... parametern: value) }
 * <br/>
 * This class parses the customer DSL used by EGL.i to lookup and run the specified groovy script.
 * 
 * @author Matyas Mazzag
 *
 */
class EGL {
	
	/** Instatiation is only done locally. */
	private EGL() {}
	
	/** Someone just typed EGL.i without a closure parameter - not very useful, tell them so. */
	static def getI() {
		showError()
	}
	
	/** Main entry point to invoke scripts. */
	static def i( Closure closure ) {
		new EGL().invoke( closure )
	}

	/**
	 * Parses the DSL, figures out log, testRunner and context variables, script name, parameters
	 * and passes all these to the ScriptRunner to do the heavy lifting.
	 */
	private def invoke( Closure closure = null ) {
		if( closure ) {
			def scriptFile, args
			closure.owner.metaClass.propertyMissing = { n -> scriptFile = n }
			closure.owner.metaClass.methodMissing = { n, a -> scriptFile = n; if( a ) { args = a[0] }}
			closure.delegate = this
			def result = closure()
			if( !result && !scriptFile ) {
				showDebug( closure )
			} else {
				if( !scriptFile ) { scriptFile = result }
				new ScriptRunner( scriptFile, args, [ 'context': closure.owner.testRunner.runContext, 'testRunner': closure.owner.testRunner, 'log': closure.owner.log, 'groovyUtils': new GroovyUtils( closure.owner.testRunner.runContext ), 'configResolver': new ConfigFilePathResolver( closure.owner.testRunner ) ] )
			}
		} else {
			showError() 
		}
		return
	}

	/** Prints where the script and config roots are pointing at (if found). */
	private static def showDebug( Closure closure ) {
		closure.owner.log.info 'EGL.i version ' + ScriptRunner.class.package.implementationVersion
		[ new ScriptFilePathResolver( closure.owner.testRunner ), new ConfigFilePathResolver( closure.owner.testRunner )].each {
			try {
				closure.owner.log.info '' + it.resolve() + " ($it.resolvedVia)"  
			} catch( Exception e ) {
				closure.owner.log.error e.message
			}
		}
	}
	
	/** Throws error with a bit of usage info. */
	private static def showError() {
		throw new IllegalArgumentException( 'Usage: EGL.i{ [external groovy file name](optional parameters) } - please pass a closure to EGL.i' )
	}
}